home *** CD-ROM | disk | FTP | other *** search
- /* threaded state machine animation system */
-
- /* Written by Dave Stampe Oct. 1992 for REND386 V5.0 */
-
- // works pretty well, with automatic time-independent animation.
- // Expensive on memory: eats 200 bytes per program line, and
- // little error trapping!
-
- // Need something more programmer-accessible too.
- // This will be added in future API release
- // This code is ported to VR-386 API, and uses the
- // auto-update list method
-
-
- /*
- This code is part of the VR-386 project, created by Dave Stampe.
- VR-386 is a desendent of REND386, created by Dave Stampe and
- Bernie Roehl. Almost all the code has been rewritten by Dave
- Stampre for VR-386.
-
- Copyright (c) 1994 by Dave Stampe:
- May be freely used to write software for release into the public domain
- or for educational use; all commercial endeavours MUST contact Dave Stampe
- (dstampe@psych.toronto.edu) for permission to incorporate any part of
- this software or source code into their products! Usually there is no
- charge for under 50-100 items for low-cost or shareware products, and terms
- are reasonable. Any royalties are used for development, so equipment is
- often acceptable payment.
-
- ATTRIBUTION: If you use any part of this source code or the libraries
- in your projects, you must give attribution to VR-386 and Dave Stampe,
- and any other authors in your documentation, source code, and at startup
- of your program. Let's keep the freeware ball rolling!
-
- DEVELOPMENT: VR-386 is a effort to develop the process started by
- REND386, improving programmer access by rewriting the code and supplying
- a standard API. If you write improvements, add new functions rather
- than rewriting current functions. This will make it possible to
- include you improved code in the next API release. YOU can help advance
- VR-386. Comments on the API are welcome.
-
- CONTACT: dstampe@psych.toronto.edu
- */
-
-
- #include <stdio.h>
- #include <stdlib.h> /* malloc() */
- #include <conio.h> /* kbhit() */
- #include <string.h>
-
- #include "vr_api.h"
- #include "intmath.h"
- #include "segment.h"
-
- extern void connect_body(OBJECT *s);
- extern void disconnect_body();
-
- /* from world.c */
-
- typedef struct _name NAMEREF;
-
- struct _name {
- char *name;
- void *value;
- NAMEREF *next;
- };
-
- extern NAMEREF *add_name(NAMEREF **list, char *name, void *value);
- extern void del_namelist(NAMEREF *list);
- extern void *find_name(NAMEREF *list, char *name);
- extern OBJECT *find_seg(char *name);
-
- extern int flymode;
-
- #define FREE 0 /* state (instruction) type */
- #define STEP 1
- #define MOVETO 2
- #define POSTEST 3
- #define ROTTEST 4
- #define SET 5
- #define SENSOR 6
- #define SELECTED 7
- #define TIMER 8
- #define GRAVITY 9
- #define POSLIMIT 10
- #define ROTLIMIT 11
- #define USEREP 12
- #define ABSTEP 13
- #define ATTACH 14
- #define POPTEXT 15
-
- #define SAME 0 /* status of timer and gravity */
- #define CHANGED 1
- #define EXPIRED 2
-
- typedef struct _state {
- int type; /* type of operation */
- int status; /* marks timer, gravity */
- struct _state *next; /* next operation in state */
- int tst1v, tst1i; /* evaluation tests */
- int tst2v, tst2i;
- struct _state *sstate; /* "set" assignments, next state */
- int set1v, set1i;
- int set2v, set2i;
- int set3v, set3i;
- struct _state *rstate; /* "reset" same */
- int rst1v, rst1i;
- int rst2v, rst2i;
- int rst3v, rst3i;
- OBJECT *seg; /* segment to use */
- long x1, y1, z1; /* numerical arg's */
- long x2, y2, z2; /* 1 = po's'n 2 = rotate */
- long x3, y3, z3; /* 3 = gravity accel */
- unsigned xo1, yo1, zo1; /* underflows */
- unsigned xo2, yo2, zo2;
- struct _state *ulist; /* list of seg's moved */
- } STATE;
-
- typedef struct _ani {
- struct _ani *next; /* next animation task */
- long last_time; /* last time run */
- long period; /* delay between runs */
- STATE *lstate; /* set if state has changed */
- STATE *state; /* current state in machine */
- } ANIMATION;
-
- static ANIMATION *anilist = NULL;
- static ANIMATION *cur_ani = NULL;
- static STATE *cur_state = NULL;
- static STATE *update_list = NULL;
- static STATE *update_end = NULL;
-
- NAMEREF *statelist = NULL;
- NAMEREF *varlist = NULL;
-
- #define VARIABLES 200
- static int vars[VARIABLES];
- static int varcount = 0;
-
- extern NAMEREF *figurelist;
- extern NAMEREF *fixedolist;
- extern OBJECT *body_seg, *head_seg, *wrist_seg;
-
- static long ctime;
-
- void create_default_segs()
- {
- if(!body_seg) body_seg = create_invisible_object();
- if(!head_seg) head_seg = create_invisible_object();
- if(!wrist_seg) wrist_seg = create_invisible_object();
-
- add_name(&figurelist, "user_body", body_seg);
- add_name(&figurelist, "user_head", head_seg);
- add_name(&figurelist, "user_hand", wrist_seg);
- }
-
- static void dump_states(void) /* remove states in preparation for new animation */
- {
- del_namelist(statelist);
- statelist = NULL;
- }
-
-
- static int varindex(char *name) /* return index of variable, or allocate new */
- {
- void *v;
-
- if ((v = find_name(varlist, name))!=NULL)
- {
- return (int)v;
- }
- else
- {
- if (varcount == VARIABLES-1) return 0;
- else
- {
- varcount++;
- v = (void *) varcount;
- if (add_name(&varlist, name, v)) return varcount;
- else return 0;
- }
- }
- }
-
-
- static STATE * stateptr(char *name) /* return adr. of state, or allocate new */
- {
- STATE *v;
-
- if ((v = find_name(statelist, name))!=NULL)
- {
- return v;
- }
- else
- {
- v = (STATE *) malloc(sizeof(STATE));
- if (v == NULL) return NULL;
- else
- { /* mark as usable as first command in state */
- v->type = FREE;
- if (add_name(&statelist, name, v)) return v;
- else return NULL;
- }
- }
- }
-
-
- static char ps[] = " ,\t\n";
- static char st[] = "%s";
-
- void parse_ani()
- {
- float period = 10;
- ANIMATION *ani, *a;
-
- dump_states();
- period = atof(strtok(NULL,ps));
- ani = (ANIMATION *)malloc(sizeof(ANIMATION));
- if (ani == NULL)
- {
- cur_ani = NULL;
- return;
- }
- ani->period = get_ticks_per_second()/period;
- ani->last_time = -10000000L; /* set to run immediately */
- ani->lstate = NULL;
- ani->state = NULL;
-
- ani->next = NULL; /* put it at end of list */
- if (anilist == NULL) anilist = ani;
- else
- {
- for(a = anilist;a->next;a=a->next);
- a->next = ani;
- }
- cur_ani = ani;
- }
-
-
- void parse_state()
- {
- char name[40];
-
- sscanf(strtok(NULL,ps),st, name);
- cur_state = stateptr(name); /* get new/old state adr. */
- if (cur_ani == NULL) return; /* sequence error! */
- if (cur_ani->state == NULL)
- cur_ani->state = cur_state; /* set initial state if first */
- }
-
-
- static STATE *new_state(void)
- {
- STATE *s;
-
- if (cur_state == NULL) return NULL;
- if (cur_state->type == FREE) return cur_state;
- else
- {
- s = (STATE *)malloc(sizeof(STATE));
- if (s == NULL)
- {
- cur_state = NULL;
- return NULL;
- }
- s->type = FREE;
- }
- return s;
- }
-
-
- static void parse_var(char *c, int *v, int *i)
- {
- char *cc;
-
- *i = *v = 0;
- if ((cc = strchr(c, '=')) == NULL) return;
- *cc++ = 0;
- *i = varindex(c);
- *v = atoi(cc);
- }
-
-
- static STATE *parse_as(char *c, int *v, int *i)
- {
- char *cc;
-
- if(c==NULL) // syntax error! stub off
- {
- *v = *i = 0;
- return NULL;
- }
-
- *i = *v = 0;
- if (!strcmpi(c, "EXIT")) /* keyword "exit" */
- {
- *v = -1;
- *i = -1;
- return NULL;
- }
- if ((cc = strchr(c, '=')) == NULL) return NULL;
- *cc++ = 0;
- if (strcmpi(c, "STATE"))
- {
- *v = atoi(cc);
- *i = varindex(c);
- return NULL;
- }
- else
- {
- *v = *i = 0;
- return stateptr(cc);
- }
- }
-
-
- static char *parse_assgn(char *ci, STATE *s, int set)
- {
- int v1, v2, v3, i1, i2, i3;
- STATE *ss, *sp = NULL;
- char *c, *r;
-
- if (set)
- {
- s->set1i = s->set2i = s->set3i = 0;
- s->sstate = NULL;
- }
- else
- {
- s->rst1i = s->rst2i = s->rst3i = 0;
- s->rstate = NULL;
- }
-
- if ((c = strchr(ci,'[')) == NULL) return ci; /* verify arguments */
- if ((r = strchr(c, ']')) == NULL) return ci; /* trim off enclosure */
- c++; *r++ = 0;
-
- if ((ss = parse_as(strtok(c, " ,\t"), &v1, &i1)) != NULL) sp = ss; ;
- if ((ss = parse_as(strtok(NULL, " ,\t"), &v2, &i2)) != NULL) sp = ss; ;
- if ((ss = parse_as(strtok(NULL, " ,\t"), &v3, &i3)) != NULL) sp = ss; ;
- if (set)
- {
- s->set1v = v1;
- s->set2v = v2;
- s->set3v = v3;
- s->set1i = i1;
- s->set2i = i2;
- s->set3i = i3;
- s->sstate = sp;
- }
- else
- {
- s->rst1v = v1;
- s->rst2v = v2;
- s->rst3v = v3;
- s->rst1i = i1;
- s->rst2i = i2;
- s->rst3i = i3;
- s->rstate = sp;
- }
- return r;
- }
-
-
- static long getarg(char *ci, float scale, long x)
- {
- char *c;
- double f;
-
- c = strtok(ci, " \t\n,");
- if (c == NULL || !sscanf(c, "%lf", &f) ) return x;
- return (long) (scale * f);
- }
-
-
-
- static void parse_rest(char *ci, STATE *s)
- {
- char cmd[40]="", var[40]="", segn[40]="";
- char *c, *cc, *cr;
- OBJECT *sp;
- POSE p = ZERO_POSE;
-
- sscanf(ci, "%[^([\n]", cmd); /* get segment and command */
- if (strchr(cmd,'='))
- {
- c = strchr(cmd, '='); /* split */
- *c++ = 0;
- sscanf(cmd, "%s", segn); /* strip off whitespace */
- sscanf(c,"%s", var);
- sp = find_seg(segn); /* find segment if any */
- if (!stricmp(var,"SELECTED"))
- {
- if (!sp) sp = find_name(fixedolist, segn);
- if (sp == NULL) return;
- }
- else
- {
- if (sp == NULL) return;
- find_root_object(sp); /* make sure root is current! */
- get_object_pose(sp, &p); /* and cached angle */
- }
- s->seg = sp;
- if (stricmp(var,"SET"))
- {
- if ((c = strchr(ci,'(')) == NULL) return; /* verify arguments */
- if ((cr = strchr(ci,')')) == NULL) return;
- c++; *cr++ = 0;
- }
- else cr = strchr(ci,'[');
- if (!stricmp(var, "MOVETO"))
- {
- s->x1 = getarg(c, 1, DONTCARE);
- s->y1 = getarg(NULL, 1, DONTCARE);
- s->z1 = getarg(NULL, 1, DONTCARE);
- s->x2 = getarg(NULL, 65536, DONTCARE);
- s->y2 = getarg(NULL, 65536, DONTCARE);
- s->z2 = getarg(NULL, 65536, DONTCARE);
- parse_assgn(cr, s, 1);
- s->type = MOVETO;
- }
- else if (!stricmp(var, "USEREP"))
- {
- OBJECT *o;
- if (!is_object_visible(sp)) return;
- s->seg = sp;
- s->x1 = getarg(c, 1, 0) - 1;
- parse_assgn(cr, s, 1);
- s->type = USEREP;
- }
- else if (!stricmp(var, "ATTACH"))
- {
- if (sp == NULL) return;
- s->x1 = getarg(c, 1, 1);
- parse_assgn(cr, s, 1);
- s->type = ATTACH;
- }
- else if (!stricmp(var, "STEP"))
- {
- s->x1 = getarg(c, 256, 0);
- s->y1 = getarg(NULL, 256, 0);
- s->z1 = getarg(NULL, 256, 0);
- s->x2 = getarg(NULL, 65536, 0);
- s->y2 = getarg(NULL, 65536, 0);
- s->z2 = getarg(NULL, 65536, 0);
- s->xo1 = s->yo1 = s->zo1 = 0;
- parse_assgn(cr, s, 1);
- s->type = STEP;
- }
- else if (!stricmp(var, "ABSTEP"))
- {
- s->x1 = getarg(c, 256, 0);
- s->y1 = getarg(NULL, 256, 0);
- s->z1 = getarg(NULL, 256, 0);
- s->x2 = getarg(NULL, 65536, 0);
- s->y2 = getarg(NULL, 65536, 0);
- s->z2 = getarg(NULL, 65536, 0);
- s->xo1 = s->yo1 = s->zo1 = 0;
- parse_assgn(cr, s, 1);
- s->type = ABSTEP;
- }
- else if (!stricmp(var, "GRAVITY"))
- {
- s->x2 = getarg(c, 256, 0); /* initial */
- s->y2 = getarg(NULL, 256, 0);
- s->z2 = getarg(NULL, 256, 0);
- s->x3 = getarg(NULL, 65536, 0); /* accel */
- s->y3 = getarg(NULL, 65536, 0);
- s->z3 = getarg(NULL, 65536, 0);
- s->xo1 = s->yo1 = s->zo1 = 0;
- s->xo2 = s->yo2 = s->zo2 = 0;
- parse_assgn(cr, s, 1);
- s->type = GRAVITY;
- }
- else if (!stricmp(var, "POSTEST"))
- {
- s->x1 = getarg(c, 1, -1000000000L);
- s->y1 = getarg(NULL, 1, -1000000000L);
- s->z1 = getarg(NULL, 1, -1000000000L);
- s->x2 = getarg(NULL, 1, 1000000000L);
- s->y2 = getarg(NULL, 1, 1000000000L);
- s->z2 = getarg(NULL, 1, 1000000000L);
- cr = parse_assgn(cr, s, 1);
- parse_assgn(cr, s, 0);
- s->type = POSTEST;
- }
- else if (!stricmp(var, "ROTTEST"))
- {
- s->x1 = getarg(c, 65536, DONTCARE);
- s->y1 = getarg(NULL, 65536, DONTCARE);
- s->z1 = getarg(NULL, 65536, DONTCARE);
- s->x2 = getarg(NULL, 65536, DONTCARE);
- s->y2 = getarg(NULL, 65536, DONTCARE);
- s->z2 = getarg(NULL, 65536, DONTCARE);
- cr = parse_assgn(cr, s, 1);
- parse_assgn(cr, s, 0);
- s->type = ROTTEST;
- }
- else if (!stricmp(var, "POSLIMIT"))
- {
- s->x1 = getarg(c, 1, DONTCARE);
- s->y1 = getarg(NULL, 1, DONTCARE);
- s->z1 = getarg(NULL, 1, DONTCARE);
- s->x2 = getarg(NULL, 1, DONTCARE);
- s->y2 = getarg(NULL, 1, DONTCARE);
- s->z2 = getarg(NULL, 1, DONTCARE);
- cr = parse_assgn(cr, s, 1);
- parse_assgn(cr, s, 0);
- s->type = POSLIMIT;
- }
- else if (!stricmp(var, "ROTLIMIT"))
- {
- s->x1 = getarg(c, 65536, DONTCARE);
- s->y1 = getarg(NULL, 65536, DONTCARE);
- s->z1 = getarg(NULL, 65536, DONTCARE);
- s->x2 = getarg(NULL, 65536, DONTCARE);
- s->y2 = getarg(NULL, 65536, DONTCARE);
- s->z2 = getarg(NULL, 65536, DONTCARE);
- cr = parse_assgn(cr, s, 1);
- parse_assgn(cr, s, 0);
- s->type = ROTLIMIT;
- }
- else if (!stricmp(var, "SELECTED"))
- {
- s->x1 = getarg(c, 1, 0);
- cr = parse_assgn(cr, s, 1);
- parse_assgn(cr, s, 0);
- s->type = SELECTED;
- }
- else return;
- }
- else
- {
- sscanf(cmd,"%s", var);
- if (!stricmp(var, "SET"))
- {
- parse_assgn(ci, s, 1);
- s->type = SET;
- }
- else
- {
- if ((c=strchr(ci,'('))==NULL) return; /* verify arguments */
- if ((cr=strchr(c,')'))==NULL) return;
- c++;
- *cr++ = 0;
- if (!stricmp(var, "SENSOR"))
- {
- s->x1 = getarg(c, 1, -1000000000L);
- s->y1 = getarg(NULL, 1, -1000000000L);
- s->z1 = getarg(NULL, 1, -1000000000L);
- s->x2 = getarg(NULL, 1, 1000000000L);
- s->y2 = getarg(NULL, 1, 1000000000L);
- s->z2 = getarg(NULL, 1, 1000000000L);
- cr = parse_assgn(cr, s, 1);
- parse_assgn(cr, s, 0);
- s->type = SENSOR;
- }
- else if (!stricmp(var, "POPTEXT"))
- {
- s->x1 = getarg(c, 180, 90);
- cr = parse_assgn(cr, s, 1);
- c = strtok(cr, "#\n");
- if (!c) return;
- s->seg = strdup(c);
- s->type = POPTEXT;
- }
- else if (!stricmp(var, "TIMER"))
- {
- s->x1 = getarg(c, 180, 0L);
- s->y1 = DONTCARE;
- cr = parse_assgn(cr, s, 1);
- parse_assgn(cr, s, 0);
- s->type = TIMER;
- }
- else return;
- }
- }
- s->next = NULL; /* put it at end of list */
- s->status = 1; /* force a restart */
- if (cur_state==s) return;
- cur_state->next = s;
- cur_state = s;
- }
-
-
- void parse_if()
- {
- STATE *s;
- char *c, *r;
-
- if ((s = new_state()) == NULL) return;
- c = strtok(NULL,"\n");
- if ((c = strchr(c,'(')) == NULL) return; /* verify conditional terminators */
- if ((r = strchr(c,')')) == NULL) return;
- *r++ = 0; /* trim length */
- parse_var(strtok(c+1," \t\n,"), &(s->tst1v), &(s->tst1i) );
- parse_var(strtok(NULL, " \t\n,"), &(s->tst2v), &(s->tst2i) );
- parse_rest(r, s);
- }
-
-
- void parse_do()
- {
- STATE *s;
-
- if ((s = new_state()) == NULL) return;
- s->tst1i = 0;
- parse_rest(strtok(NULL,"\n"), s);
- }
-
-
- /********************* EXECUTE *******************/
-
- static long elapsed = 0;
-
- extern void scaled_rotate(STATE *s, long *nrx,long *nry,long *nrz, long elpsed, long tps);
- extern void scaled_move(STATE *s, long *nx,long *ny,long *nz, long elapsed, long tps);
- extern void scaled_gravity(STATE *s, long elpsed, long tps);
-
-
-
-
-
- static void exec_state(STATE *s)
- {
- STATE *old_state = s;
- int changed = (s==cur_ani->lstate) ? 0 : 1 ;
- long x, y, z, rx, ry, rz;
- long nx, ny, nz, nrx, nry, nrz;
- int seg_changed = 0;
- long tps = get_ticks_per_second();
- int endstate = 0;
- POSE p;
- POSE op;
-
- cur_state = s;
- while((cur_ani->state==old_state) && s)
- {
- if (s->type == FREE) goto next_state;
- if (changed) s->status |= CHANGED;
- if (s->type == TIMER && changed) s->y1 = DONTCARE; /* reset on entry */
- if(s->type == GRAVITY && changed)
- {
- s->x1 = s->x2;
- s->y1 = s->y2;
- s->z1 = s->z2;
- s->xo1 = s->yo1 = s->zo1 = 0;
- s->xo2 = s->yo2 = s->zo2 = 0;
- }
- if (s->tst1i)
- {
- if (vars[s->tst1i] != s->tst1v) goto next_state;
- if (s->tst2i)
- {
- if (vars[s->tst2i] != s->tst2v) goto next_state;
- }
- }
- switch(s->type)
- {
- case SET:
- goto set;
-
- case SELECTED:
- if (is_object_selected(s->seg))
- {
- if (s->x1) unhighlight_object(s->seg);
- goto reset;
- }
- else goto set;
-
- case USEREP:
- {
- if (s->x1 < 0) unlock_current_representation(s->seg);
- else lock_current_representation(s->seg, s->x1);
- world_changed++;
- goto set;
- }
-
- case ATTACH:
- {
- if (s->x1 == 0)
- {
- disconnect_body();
- if (!flymode)
- {
- body_pose->rz = 0;
- }
- }
- else connect_body(s->seg);
- goto set;
- }
-
- case POPTEXT:
- {
- long t;
- if (s->seg) popmsg(s->seg);
- t = current_time()+s->x1;
- while(current_time() < t) if (kbhit()) break;
- while(kbhit()) getkey();
- world_changed++;
- goto set;
- }
-
- case SENSOR:
- {
- POSE p;
- get_camera_worldpose(current_camera, &p);
- if (s->x1 > p.x) goto set;
- if (s->x2 < p.x) goto set;
- if (s->y1 > p.y) goto set;
- if (s->y2 < p.y) goto set;
- if (s->z1 > p.z) goto set;
- if (s->z2 < p.z) goto set;
- goto reset;
- }
-
- case POSTEST:
- {
- get_object_world_position(s->seg, &p.x, &p.y, &p.z);
- if (s->x1 > p.x) goto set;
- if (s->x2 < p.x) goto set;
- if (s->y1 > p.y) goto set;
- if (s->y2 < p.y) goto set;
- if (s->z1 > p.z) goto set;
- if (s->z2 < p.z) goto set;
- goto reset;
- }
-
- case ROTTEST:
- {
- get_object_pose(s->seg, &p);
- if (s->x1 != DONTCARE && s->x1>p.rx) goto set;
- if (s->x2 != DONTCARE && s->x2<p.rx) goto set;
- if (s->y1 != DONTCARE && s->y1>p.ry) goto set;
- if (s->y2 != DONTCARE && s->y2<p.ry) goto set;
- if (s->z1 != DONTCARE && s->z1>p.rz) goto set;
- if (s->z2 != DONTCARE && s->z2<p.rz) goto set;
- goto reset;
- }
-
- case POSLIMIT:
- {
- get_object_pose(s->seg, &p);
- p.rx = p.ry = p.rz = DONTCARE;
- if (s->x1 != DONTCARE && s->x1 > p.x) { p.x = s->x1; goto rstp; }
- if (s->x2 != DONTCARE && s->x2 < p.x) { p.x = s->x2; goto rstp; }
- if (s->y1 != DONTCARE && s->y1 > p.y) { p.y = s->y1; goto rstp; }
- if (s->y2 != DONTCARE && s->y2 < p.y) { p.y = s->y2; goto rstp; }
- if (s->z1 != DONTCARE && s->z1 > p.z) { p.z = s->z1; goto rstp; }
- if (s->z2 != DONTCARE && s->z2 < p.z) { p.z = s->z2; goto rstp; }
- goto reset;
- rstp:
- seg_changed++;
- set_object_pose(s->seg, &p);
- goto move_seg;
- }
-
- case ROTLIMIT:
- {
- get_object_pose(s->seg, &p);
- p.x = p.y = p.z = DONTCARE;
- if (s->x1 != DONTCARE && s->x1 > p.rx) { p.rx = s->x1; goto rstr; }
- if (s->x2 != DONTCARE && s->x2 < p.rx) { p.rx = s->x2; goto rstr; }
- if (s->y1 != DONTCARE && s->y1 > p.ry) { p.ry = s->y1; goto rstr; }
- if (s->y2 != DONTCARE && s->y2 < p.ry) { p.ry = s->y2; goto rstr; }
- if (s->z1 != DONTCARE && s->z1 > p.rz) { p.rz = s->z1; goto rstr; }
- if (s->z2 != DONTCARE && s->z2 < p.rz) { p.rz = s->z2; goto rstr; }
- goto reset;
- rstr:
- seg_changed++;
- set_object_pose(s->seg, &p);
- goto move_seg;
- }
-
- case MOVETO:
- {
- get_object_pose(s->seg, &p);
- op = p;
- if (s->x1 != DONTCARE){ p.x = s->x1; s->xo1 = 0; } /* set pos'n, zero underflow */
- if (s->y1 != DONTCARE){ p.y = s->y1; s->yo1 = 0; }
- if (s->z1 != DONTCARE){ p.z = s->z1; s->zo1 = 0; }
- if (s->x2 != DONTCARE) p.rx = s->x2;
- if (s->y2 != DONTCARE) p.ry = s->y2;
- if (s->z2 != DONTCARE) p.rz = s->z2;
- if (memcmp(&p,&op,sizeof(POSE)))
- {
- seg_changed++;
- set_object_pose(s->seg, &p);
- }
- if (seg_changed) goto move_seg; else goto set;
- }
-
- case ABSTEP:
- tps = 0; // turns off time scaling
- case STEP:
- {
- do_posstep:
- get_object_pose(s->seg, &p);
- op = p;
- // asm code to rotate, scaled by time
- scaled_rotate(s, &p.rx, &p.ry, &p.rz, elapsed, tps);
- // asm code to translate, scaled by time
- scaled_move(s, &p.x, &p.y, &p.z, elapsed, tps);
-
- if (memcmp(&p,&op,sizeof(POSE)))
- {
- seg_changed++;
- set_object_pose(s->seg, &p);
- }
- if (seg_changed) goto move_seg; else goto set;
- }
-
- case GRAVITY:
- {
- // asm code to update velocities
-
- scaled_gravity(s, elapsed, tps);
-
- goto do_posstep; /* now treat as normal motion */
- }
-
- case TIMER:
- {
- if (s->y1 == DONTCARE) s->y1 = ctime+s->x1;
- if (s->y1 < ctime)
- goto reset;
- else goto set;
- }
-
- reset:
- if (s->rst1i > 0) vars[s->rst1i] = s->rst1v; /* do all setup stuff */
- else if (s->rst1i < 0) endstate++;
- if (s->rst2i > 0) vars[s->rst2i] = s->rst2v;
- else if (s->rst2i < 0) endstate++;
- if (s->rst3i > 0) vars[s->rst3i] = s->rst3v;
- else if (s->rst3i < 0) endstate++;
- if (s->rstate)
- {
- cur_ani->state = s->rstate;
- goto newstate;
- }
- break;
-
- move_seg: // AUTO UPDATE LIST
- add_to_object_update_list(s->seg);
-
- set:
- if (s->set1i > 0) vars[s->set1i] = s->set1v;
- else if (s->set1i < 0) endstate++;
- if (s->set2i > 0) vars[s->set2i] = s->set2v;
- else if (s->set2i < 0) endstate++;
- if (s->set3i > 0) vars[s->set3i] = s->set3v;
- else if (s->set3i < 0) endstate++;
- if (s->sstate)
- {
- cur_ani->state = s->sstate;
- goto newstate;
- }
- break;
-
- default: break;
- }
-
- next_state:
- if (endstate) s = NULL;
- else s = s->next;
- }
-
- newstate:
- cur_ani->lstate = old_state;
- }
-
-
-
- void do_animations()
- {
- SEGMENT *s;
- unsigned flags;
- ANIMATION *ani = anilist;
-
- ctime = current_time();
- update_list = NULL;
-
- while(ani)
- {
- if (ani->last_time < ctime) /* time to animate? */
- {
- elapsed = ctime+ani->period-ani->last_time;
- if (elapsed > 2000) elapsed = 2000; // at least once ev. 2 sec
- ani->last_time = ctime+ani->period;
- cur_ani = ani;
- exec_state(ani->state);
- }
- ani = ani->next;
- }
-
- // PROCESS ALL CHANGES AUTOMATICALLY
- world_changed |= process_object_update_list();
- }
-
-
-
-
-
-
-